import {Injectable} from '@angular/core';
import {HttpClient, HttpParams, HttpHeaders} from '@angular/common/http';
import { HTTP } from '@ionic-native/http/ngx';
import { Device } from '@ionic-native/device/ngx';
import * as querystring from 'querystring';
import { ToastService } from './toast.service';
import {HttpBase} from './http.base';
import {TranslateService} from '@ngx-translate/core';

function prefixZero(num, n = 2) {
    return (Array(n).join('0') + num).slice(-n);
}

@Injectable({
    providedIn: 'root'
})
export class HttpService extends HttpBase {

    readonly methodArray = ['GET', 'DELETE', 'POST', 'PUT'];
    endPointUrl: string;
    options: any = {};

    constructor(
        private httpClient: HttpClient,
        private httpNative: HTTP,
        private device: Device,
        private translate: TranslateService,
        private toastSrv: ToastService) {
        super();
        this.endPointUrl = this.getEndPoint(!!this.device.platform);
    }

    public getDateString(setDate = null) {
        if (setDate) {
            const queryDate = new Date(setDate);
            const orderYear = queryDate.getUTCFullYear();
            const orderMonth = prefixZero(queryDate.getUTCMonth() + 1);
            const orderDay = prefixZero(queryDate.getUTCDate());
            return `${orderYear}-${orderMonth}-${orderDay}`;
        } else {
            const queryDate = new Date();
            const orderYear = queryDate.getFullYear();
            const orderMonth = prefixZero(queryDate.getMonth() + 1);
            const orderDay = prefixZero(queryDate.getDate());
            return `${orderYear}-${orderMonth}-${orderDay}`;
        }
    }

    public getDatetimeString(setDate = null) {
        if (setDate) {
            const queryDate = new Date();
            const orderYear = queryDate.getUTCFullYear();
            const orderMonth = prefixZero(queryDate.getUTCMonth() + 1);
            const orderDay = prefixZero(queryDate.getUTCDate());
            const orderHours = prefixZero(queryDate.getUTCHours());
            const orderMinute = prefixZero(queryDate.getUTCMinutes());
            return `${orderYear}-${orderMonth}-${orderDay} ${orderHours}:${orderMinute}`;
        } else {
            const queryDate = new Date();
            const orderYear = queryDate.getFullYear();
            const orderMonth = prefixZero(queryDate.getMonth() + 1);
            const orderDay = prefixZero(queryDate.getDate());
            const orderHours = prefixZero(queryDate.getHours());
            const orderMinute = prefixZero(queryDate.getMinutes());
            return `${orderYear}-${orderMonth}-${orderDay} ${orderHours}:${orderMinute}`;
        }
    }

    public getTomorrowDateString() {
        const queryDate = new Date();
        queryDate.setDate(queryDate.getDate() + 1);
        queryDate.setHours(0);
        queryDate.setMinutes(0);
        const orderYear = queryDate.getFullYear();
        const orderMonth = prefixZero(queryDate.getMonth() + 1);
        const orderDay = prefixZero(queryDate.getDate());
        const orderHours = prefixZero(queryDate.getHours());
        const orderMinute = prefixZero(queryDate.getMinutes());
        return `${orderYear}-${orderMonth}-${orderDay} ${orderHours}:${orderMinute}`;
    }

    public getTimezoneOffset = () => {
        const queryDate = new Date();
        return queryDate.getTimezoneOffset() / 60;
    }

    public get() {
        this.options.method = this.methodArray[0];
        return this;
    }

    public delete() {
        this.options.method = this.methodArray[1];
        return this;
    }

    public post() {
        this.options.method = this.methodArray[2];
        return this;
    }

    public put() {
        this.options.method = this.methodArray[3];
        return this;
    }

    public setHeader(header: any = {}) {
        this.options.header = header;
        return this;
    }

    public setUrl(url: string) {
        this.options.url = url;
        return this;
    }

    public setPath(path: string) {
        this.options.path = path;
        return this;
    }

    public setQuery(query: any = {}) {
        if (this.device.platform) {
            this.options.params = query;
        } else {
            const paramsOptions = {fromString: querystring.stringify(query)};
            this.options.params = new HttpParams(paramsOptions);
        }
        return this;
    }

    public setBody(body: any = {}) {
        this.options.body = body;
        return this;
    }

    public async request() {
        const { method = 'GET', url, path, params, body = {} } = this.options;

        const headerOptions: any = {
            lang: this.translate.getBrowserCultureLang()
        };
        const authToken = localStorage.getItem('auth-token');
        if (authToken) {
            headerOptions.Authorization = authToken;
        }

        let options: any = {};
        if (this.device.platform) {
            switch (method) {
                case 'GET':
                case 'DELETE':
                    headerOptions['Content-Type'] = 'application/json';
                    break;

                case 'POST':
                case 'PUT':
                    headerOptions['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
                    break;
            }
            options = { method, headers: headerOptions, data: body };
        } else {
            headerOptions['Content-Type'] = 'application/json';
            const headers = new HttpHeaders(headerOptions);
            options = { headers, params, body };
        }

        try {
            let requestUrl = url || this.endPointUrl + path;
            let result: any = {};
            if (this.device.platform) {
                if (params) {
                    requestUrl += `?${querystring.stringify(params)}`;
                }
                // @ts-ignore
                result = await this.httpNative.sendRequest(requestUrl, options).then(resp => JSON.parse(resp.data));
            } else {
                result = await this.httpClient.request(method, requestUrl, options).toPromise();
            }

            if (result.status !== 0) {
                this.toastSrv.showToast(result.message);
                if (result.status === 9) {
                    localStorage.removeItem('auth-token');
                }
            }
            return result;
        } catch (error) {
            console.log('error:', error.message);
            this.toastSrv.setDuration(5000).showToast(error.message);
        } finally {
            this.options = {};
        }
    }
}
